﻿﻿﻿using jiuyuan.数据.基础数据类;
using jiuyuan.数据.怪物类;
using jiuyuan.数据.玩家类;
using jiuyuan.数据.用户类; // 添加用户类引用
using jiuyuan.管理器;
using Microsoft.EntityFrameworkCore;
using System.Text.Json;

namespace jiuyuan.服务;

// 数据库上下文（EF Core）
public class 游戏数据库上下文(DbContextOptions<游戏数据库上下文> options) : DbContext(options)
{
    public DbSet<技能配置> 技能配置表 { get; set; } = null!;
    public DbSet<技能效果> 技能效果表 { get; set; } = null!;
    public DbSet<装备物品> 装备表 { get; set; } = null!;
    public DbSet<怪物> 怪物表 { get; set; } = null!;
    public DbSet<副本配置> 副本配置表 { get; set; } = null!;
    public DbSet<玩家> 玩家表 { get; set; } = null!;
    public DbSet<持续效果> 持续效果表 { get; set; } = null!;
    public DbSet<游戏元素> 游戏元素表 { get; set; } = null!;
    
    // 添加效果配置表
    public DbSet<效果配置> 效果配置表 { get; set; } = null!;
    
    // 添加用户相关的DbSet
    public DbSet<用户> 用户表 { get; set; } = null!;
    public DbSet<玩家角色> 玩家角色表 { get; set; } = null!;

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        // 配置技能效果的多态性
        modelBuilder.Entity<技能效果>()
            .HasDiscriminator<string>("效果类型")
            .HasValue<伤害效果>("伤害效果")
            .HasValue<治疗效果>("治疗效果")
            .HasValue<增益效果>("增益效果")
            .HasValue<持续伤害效果>("持续伤害效果")
            .HasValue<属性加成效果>("属性加成效果")
            .HasValue<动态技能效果>("动态技能效果")
            .HasValue<动态伤害效果>("动态伤害效果")
            .HasValue<动态治疗效果>("动态治疗效果")
            .HasValue<动态属性增益效果>("动态属性增益效果")
            .HasValue<动态速度减益效果>("动态速度减益效果");

        // 配置技能效果的参数Json属性
        modelBuilder.Entity<技能效果>()
            .Property(e => e.参数Json)
            .HasColumnName("参数")
            .IsRequired();

        // 忽略参数字典属性，因为它通过参数Json属性进行序列化存储
        modelBuilder.Entity<技能效果>()
            .Ignore(e => e.参数);

        // 配置装备特效的多态性
        modelBuilder.Entity<装备特效>()
            .HasDiscriminator<string>("特效类型")
            .HasValue<属性加成特效>("属性加成特效")
            .HasValue<技能增强特效>("技能增强特效");

        // 配置具体实体的属性配置，不配置基类
        modelBuilder.Entity<技能配置>()
            .OwnsOne(s => s.基础属性);

        modelBuilder.Entity<装备物品>()
            .OwnsOne(e => e.基础属性);

        modelBuilder.Entity<游戏元素>()
            .OwnsOne(e => e.基础属性);

        // 为游戏元素配置效果列表的关系
        modelBuilder.Entity<游戏元素>()
            .HasMany(e => e.效果列表)
            .WithOne()
            .OnDelete(DeleteBehavior.Cascade);

        // 为怪物配置属性
        modelBuilder.Entity<怪物>(entity => {
            entity.OwnsOne(m => m.基础属性);
            entity.OwnsOne(m => m.当前属性);
        });

        // 为玩家配置属性
        modelBuilder.Entity<玩家>(entity => {
            entity.OwnsOne(p => p.基础属性);
            entity.OwnsOne(p => p.当前属性);
        });

        // 为增益效果配置增益属性
        modelBuilder.Entity<增益效果>(entity => {
            entity.OwnsOne(e => e.增益属性);
        });

        modelBuilder.Entity<属性加成特效>()
            .OwnsOne(e => e.加成属性);

        // 为怪物生成配置指定主键
        modelBuilder.Entity<怪物生成配置>(entity => {
            entity.HasKey(e => e.怪物ID);
        });

        // 为掉落物品指定主键
        modelBuilder.Entity<掉落物品>(entity => {
            entity.HasKey(e => e.物品ID);
            // 配置物品详情的导航属性
            entity.HasOne(e => e.物品详情)
                .WithMany()
                .HasForeignKey(e => e.物品ID)
                .OnDelete(DeleteBehavior.Cascade);
        });

        // 配置战斗单位和持续效果的关系
        modelBuilder.Entity<战斗单位>()
            .HasMany(e => e.持续效果列表)
            .WithOne(e => e.目标)
            .HasForeignKey(e => e.目标Id)
            .OnDelete(DeleteBehavior.Cascade);

        // 为持续效果配置施加者关系
        modelBuilder.Entity<持续效果>()
            .HasOne(e => e.施加者)
            .WithMany()
            .HasForeignKey(e => e.施加者Id)
            .OnDelete(DeleteBehavior.NoAction);
            
        // 配置持续效果的参数字典
        modelBuilder.Entity<持续效果>()
            .Property(e => e.参数)
            .HasConversion(
                v => JsonSerializer.Serialize(v, new JsonSerializerOptions()),
                v => JsonSerializer.Deserialize<Dictionary<string, object>>(v, new JsonSerializerOptions())
            )
            .HasColumnType("jsonb");

        // 配置用户和玩家角色的关系
        modelBuilder.Entity<玩家角色>(entity => {
            entity.HasOne(pr => pr.用户)
                .WithMany(u => u.玩家角色列表)
                .HasForeignKey(pr => pr.用户Id)
                .OnDelete(DeleteBehavior.Cascade);
                
            // 配置玩家角色和游戏实例的关系
            entity.HasOne(pr => pr.游戏玩家)
                .WithOne()
                .HasForeignKey<玩家角色>(pr => pr.游戏玩家Id)
                .OnDelete(DeleteBehavior.Cascade);
        });
        
        // 配置效果配置表
        modelBuilder.Entity<效果配置>(entity => {
            entity.HasKey(e => e.Id);
            entity.Property(e => e.参数)
                .HasConversion(
                    v => JsonSerializer.Serialize(v, new JsonSerializerOptions()),
                    v => JsonSerializer.Deserialize<Dictionary<string, object>>(v, new JsonSerializerOptions())
                )
                .HasColumnType("jsonb");
        });
    }
}

// 效果配置数据类
public class 效果配置
{
    public Guid Id { get; set; } = Guid.CreateVersion7();
    public string 名称 { get; set; } = "";
    public string 描述 { get; set; } = "";
    public string 效果类型 { get; set; } = ""; // 伤害、治疗、增益、减益、控制等
    public string 触发时机 { get; set; } = "立即";
    public int 持续回合数 { get; set; } = 0;
    public float 触发概率 { get; set; } = 1.0f;

    // 参数存储
    public Dictionary<string, object> 参数 { get; set; } = new();

    public DateTime 创建时间 { get; set; } = DateTime.Now;
    public DateTime 更新时间 { get; set; } = DateTime.Now;
    public bool 是否启用 { get; set; } = true;
}

// 配置加载器
public class 配置加载器
{
    private readonly IServiceProvider _serviceProvider;
    private readonly ILogger<配置加载器> _logger;
    private readonly 游戏数据库上下文 _数据库上下文;
    
    // 延迟加载依赖项
    private 技能管理器? _技能管理器;
    private 装备管理器? _装备管理器;
    private 效果管理器? _效果管理器;
    private 元素管理器? _元素管理器;

    public 配置加载器(
        游戏数据库上下文 数据库上下文,
        ILogger<配置加载器> logger,
        IServiceProvider serviceProvider)
    {
        _数据库上下文 = 数据库上下文;
        _logger = logger;
        _serviceProvider = serviceProvider;
    }

    // 延迟获取依赖项
    private 技能管理器 技能管理器 => _技能管理器 ??= _serviceProvider.GetRequiredService<技能管理器>();
    private 装备管理器 装备管理器 => _装备管理器 ??= _serviceProvider.GetRequiredService<装备管理器>();
    private 效果管理器 效果管理器 => _效果管理器 ??= _serviceProvider.GetRequiredService<效果管理器>();
    private 元素管理器 元素管理器 => _元素管理器 ??= _serviceProvider.GetRequiredService<元素管理器>();

    /// <summary>
    /// 从数据库加载所有游戏配置
    /// </summary>
    public async Task 加载所有配置()
    {
        _logger.LogInformation("开始从数据库加载所有游戏配置...");

        // 加载效果配置
        await 加载效果配置();

        // 加载技能
        await 加载技能配置();

        // 加载装备
        await 加载装备配置();

        // 加载游戏元素
        await 加载游戏元素配置();

        // 加载怪物
        await 加载怪物配置();

        // 加载副本
        await 加载副本配置();

        _logger.LogInformation("所有游戏配置加载完成");
    }

    /// <summary>
    /// 加载效果配置
    /// </summary>
    private async Task 加载效果配置()
    {
        try
        {
            var 效果列表 = await _数据库上下文.效果配置表.ToListAsync();

            foreach (var 效果 in 效果列表)
            {
                _效果管理器.注册效果配置(效果);
                _logger.LogDebug("加载效果配置: {效果名称}, ID: {效果ID}", 效果.名称, 效果.Id);
            }

            _logger.LogInformation("加载效果配置完成: {效果数量} 个", 效果列表.Count);
        }
        catch (Exception 异常)
        {
            _logger.LogError(异常, "加载效果配置时发生错误");
            throw;
        }
    }

    /// <summary>
    /// 加载技能配置
    /// </summary>
    private async Task 加载技能配置()
    {
        try
        {
            var 技能列表 = await _数据库上下文.技能配置表
                .Include(s => s.效果列表)
                .ToListAsync();

            foreach (var 技能 in 技能列表)
            {
                _技能管理器.注册技能(技能);
                _logger.LogDebug("加载技能: {技能名称}, ID: {技能ID}, 效果数量: {效果数量}",
                    技能.名称, 技能.Id, 技能.效果列表.Count);
            }

            _logger.LogInformation("加载技能配置完成: {技能数量} 个", 技能列表.Count);
        }
        catch (Exception 异常)
        {
            _logger.LogError(异常, "加载技能配置时发生错误");
            throw;
        }
    }

    /// <summary>
    /// 加载装备配置
    /// </summary>
    private async Task 加载装备配置()
    {
        try
        {
            var 装备列表 = await _数据库上下文.游戏元素表.Where(e=>e.类型 == 数据.共享类.物品类型.装备)
                .Include(e => e.效果列表)
                .ToListAsync();

            foreach (var 装备1 in 装备列表)
            {
                if(装备1 is 装备物品 装备2)
                {
                    _装备管理器.注册装备(装备2);
                    _logger.LogDebug("加载装备: {装备名称}, ID: {装备ID}, 槽位: {装备槽位}",
                        装备2.名称, 装备2.Id, 装备2.槽位);
                }
                
            }

            _logger.LogInformation("加载装备配置完成: {装备数量} 个", 装备列表.Count);
        }
        catch (Exception 异常)
        {
            _logger.LogError(异常, "加载装备配置时发生错误");
            throw;
        }
    }

    /// <summary>
    /// 加载游戏元素配置
    /// </summary>
    public async Task 加载游戏元素配置()
    {
        try
        {
            var 元素列表 = await _数据库上下文.游戏元素表
                .Include(e => e.效果列表)
                .ToListAsync();

            foreach (var 元素 in 元素列表)
            {
                _元素管理器.注册元素(元素);
                _logger.LogDebug("加载游戏元素: {元素名称}, ID: {元素ID}, 类型: {元素类型}",
                    元素.名称, 元素.Id, 元素.类型);
            }

            _logger.LogInformation("加载游戏元素配置完成: {元素数量} 个", 元素列表.Count);
        }
        catch (Exception 异常)
        {
            _logger.LogError(异常, "加载游戏元素配置时发生错误");
            throw;
        }
    }

    /// <summary>
    /// 加载怪物配置
    /// </summary>
    private async Task 加载怪物配置()
    {
        try
        {
            var 怪物列表 = await _数据库上下文.怪物表
                .Include(m => m.技能列表)
                .Include(m => m.掉落列表)
                .ThenInclude(d => d.物品详情)
                .ToListAsync();

            _logger.LogInformation("加载怪物配置完成: {怪物数量} 个", 怪物列表.Count);
        }
        catch (Exception 异常)
        {
            _logger.LogError(异常, "加载怪物配置时发生错误");
            throw;
        }
    }

    /// <summary>
    /// 加载副本配置
    /// </summary>
    private async Task 加载副本配置()
    {
        try
        {
            var 副本列表 = await _数据库上下文.副本配置表
                .Include(f => f.怪物生成配置列表)
                .ThenInclude(m => m.怪物详情)
                .ThenInclude(m => m!.技能列表)
                .Include(f => f.通关奖励)
                .ThenInclude(r => r.物品详情)
                .ToListAsync();

            _logger.LogInformation("加载副本配置完成: {副本数量} 个", 副本列表.Count);
        }
        catch (Exception 异常)
        {
            _logger.LogError(异常, "加载副本配置时发生错误");
            throw;
        }
    }

    /// <summary>
    /// 保存效果配置到数据库
    /// </summary>
    public async Task 保存效果配置(效果配置 效果)
    {
        try
        {
            if (await _数据库上下文.效果配置表.AnyAsync(e => e.Id == 效果.Id))
            {
                _数据库上下文.效果配置表.Update(效果);
            }
            else
            {
                await _数据库上下文.效果配置表.AddAsync(效果);
            }

            await _数据库上下文.SaveChangesAsync();
            _logger.LogInformation("保存效果配置: {效果名称}, ID: {效果ID}", 效果.名称, 效果.Id);
        }
        catch (Exception 异常)
        {
            _logger.LogError(异常, "保存效果配置时发生错误");
            throw;
        }
    }

    /// <summary>
    /// 删除效果配置
    /// </summary>
    public async Task 删除效果配置(Guid 效果ID)
    {
        try
        {
            var 效果 = await _数据库上下文.效果配置表.FindAsync(效果ID);
            if (效果 != null)
            {
                _数据库上下文.效果配置表.Remove(效果);
                await _数据库上下文.SaveChangesAsync();
                _logger.LogInformation("删除效果配置: ID: {效果ID}", 效果ID);
            }
        }
        catch (Exception 异常)
        {
            _logger.LogError(异常, "删除效果配置时发生错误");
            throw;
        }
    }

    /// <summary>
    /// 从数据库获取所有效果配置
    /// </summary>
    public async Task<List<效果配置>> 获取所有效果配置()
    {
        return await _数据库上下文.效果配置表.ToListAsync();
    }

    /// <summary>
    /// 保存技能配置到数据库
    /// </summary>
    public async Task 保存技能配置(技能配置 技能)
    {
        try
        {
            if (!await _数据库上下文.技能配置表.AnyAsync(e => e.Id == 技能.Id))
            {
                技能.更新时间 = DateTime.Now;
                await _数据库上下文.技能配置表.AddAsync(技能);
            }
            else
            {
                _数据库上下文.技能配置表.Update(技能);
            }

            await _数据库上下文.SaveChangesAsync();
            _logger.LogInformation("保存技能配置: {技能名称}, ID: {技能ID}", 技能.名称, 技能.Id);
        }
        catch (Exception 异常)
        {
            _logger.LogError(异常, "保存技能配置时发生错误");
            throw;
        }
    }

    /// <summary>
    /// 保存效果配置到数据库
    /// </summary>
    public async Task 保存效果配置(技能效果 效果)
    {
        try
        {
            if (await _数据库上下文.技能效果表.AnyAsync(e => e.Id == 效果.Id))
            {
                _数据库上下文.技能效果表.Update(效果);
            }
            else
            {
                await _数据库上下文.技能效果表.AddAsync(效果);
            }

            await _数据库上下文.SaveChangesAsync();
            _logger.LogInformation("保存效果配置: {效果名称}, ID: {效果ID}", 效果.效果名称, 效果.Id);
        }
        catch (Exception 异常)
        {
            _logger.LogError(异常, "保存效果配置时发生错误");
            throw;
        }
    }

    /// <summary>
    /// 保存装备配置到数据库
    /// </summary>
    public async Task 保存装备配置(装备物品 装备)
    {
        try
        {
            if (await _数据库上下文.装备表.AnyAsync(e => e.Id == 装备.Id))
            {
                装备.更新时间 = DateTime.Now;
                _数据库上下文.装备表.Update(装备);
            }
            else
            {
                await _数据库上下文.装备表.AddAsync(装备);
            }

            await _数据库上下文.SaveChangesAsync();
            _logger.LogInformation("保存装备配置: {装备名称}, ID: {装备ID}", 装备.名称, 装备.Id);
        }
        catch (Exception 异常)
        {
            _logger.LogError(异常, "保存装备配置时发生错误");
            throw;
        }
    }

    /// <summary>
    /// 保存游戏元素配置到数据库
    /// </summary>
    public async Task 保存游戏元素(游戏元素 元素)
    {
        try
        {
            if (await _数据库上下文.游戏元素表.AnyAsync(e => e.Id == 元素.Id))
            {
                元素.更新时间 = DateTime.Now;
                _数据库上下文.游戏元素表.Update(元素);
            }
            else
            {
                await _数据库上下文.游戏元素表.AddAsync(元素);
            }

            await _数据库上下文.SaveChangesAsync();
            _logger.LogInformation("保存游戏元素: {元素名称}, ID: {元素ID}", 元素.名称, 元素.Id);
        }
        catch (Exception 异常)
        {
            _logger.LogError(异常, "保存游戏元素时发生错误");
            throw;
        }
    }

    /// <summary>
    /// 删除游戏元素配置
    /// </summary>
    public async Task 删除游戏元素(Guid 元素ID)
    {
        try
        {
            var 元素 = await _数据库上下文.游戏元素表.FindAsync(元素ID);
            if (元素 != null)
            {
                _数据库上下文.游戏元素表.Remove(元素);
                await _数据库上下文.SaveChangesAsync();
                _logger.LogInformation("删除游戏元素: ID: {元素ID}", 元素ID);
            }
        }
        catch (Exception 异常)
        {
            _logger.LogError(异常, "删除游戏元素时发生错误");
            throw;
        }
    }

    /// <summary>
    /// 保存怪物配置到数据库
    /// </summary>
    public async Task 保存怪物配置(怪物 怪物)
    {
        try
        {
            if (await _数据库上下文.怪物表.AnyAsync(e => e.Id == 怪物.Id))
            {
                _数据库上下文.怪物表.Update(怪物);
            }
            else
            {
                await _数据库上下文.怪物表.AddAsync(怪物);
            }

            await _数据库上下文.SaveChangesAsync();
            _logger.LogInformation("保存怪物配置: {怪物名称}, ID: {怪物ID}", 怪物.名称, 怪物.Id);
        }
        catch (Exception 异常)
        {
            _logger.LogError(异常, "保存怪物配置时发生错误");
            throw;
        }
    }

    /// <summary>
    /// 保存副本配置到数据库
    /// </summary>
    public async Task 保存副本配置(副本配置 副本)
    {
        try
        {
            if (await _数据库上下文.副本配置表.AnyAsync(e => e.Id == 副本.Id))
            {
                _数据库上下文.副本配置表.Update(副本);
            }
            else
            {
                await _数据库上下文.副本配置表.AddAsync(副本);
            }

            await _数据库上下文.SaveChangesAsync();
            _logger.LogInformation("保存副本配置: {副本名称}, ID: {副本ID}", 副本.名称, 副本.Id);
        }
        catch (Exception 异常)
        {
            _logger.LogError(异常, "保存副本配置时发生错误");
            throw;
        }
    }

    /// <summary>
    /// 从数据库获取所有技能
    /// </summary>
    public async Task<List<技能配置>> 获取所有技能()
    {
        return await _数据库上下文.技能配置表
            .Include(s => s.效果列表)
            .ToListAsync();
    }

    /// <summary>
    /// 从数据库获取所有效果
    /// </summary>
    public async Task<List<技能效果>> 获取所有效果()
    {
        return await _数据库上下文.技能效果表.ToListAsync();
    }

    /// <summary>
    /// 从数据库获取所有装备
    /// </summary>
    public async Task<List<装备物品>> 获取所有装备()
    {
        return await _数据库上下文.装备表
            .Include(e => e.特效列表)
            .ToListAsync();
    }

    /// <summary>
    /// 从数据库获取所有游戏元素
    /// </summary>
    public async Task<List<游戏元素>> 获取所有游戏元素()
    {
        return await _数据库上下文.游戏元素表
            .Include(e => e.效果列表)
            .ToListAsync();
    }

    /// <summary>
    /// 从数据库获取所有怪物
    /// </summary>
    public async Task<List<怪物>> 获取所有怪物()
    {
        return await _数据库上下文.怪物表.ToListAsync();
    }

    /// <summary>
    /// 从数据库获取所有副本
    /// </summary>
    public async Task<List<副本配置>> 获取所有副本()
    {
        return await _数据库上下文.副本配置表
            .Include(f => f.事件节点列表)
            .ThenInclude(n => n.怪物生成列表)
            .ThenInclude(m => m.怪物详情)
            .Include(f => f.事件节点列表)
            .ThenInclude(n => n.掉落物品列表)
            .ThenInclude(r => r.物品详情)
            .ToListAsync();
    }

    /// <summary>
    /// 从数据库获取所有玩家
    /// </summary>
    public async Task<List<玩家>> 获取所有玩家()
    {
        return await _数据库上下文.玩家表.ToListAsync();
    }
}